//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Media3D;

namespace OpenLS.Chart.UI.Internals
{
    public class CameraPanel : Panel
    {


        public Camera3D2DProjector Projector
        {
            get { return (Camera3D2DProjector)GetValue(ProjectorProperty); }
            set { SetValue(ProjectorProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Projector.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ProjectorProperty =
            DependencyProperty.Register("Projector", typeof(Camera3D2DProjector), typeof(CameraPanel), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsArrange));


        public static readonly DependencyProperty CameraProperty =
            DependencyProperty.Register("Camera", typeof (Camera), typeof (CameraPanel), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.AffectsArrange));

        public static readonly DependencyProperty XProperty =
            DependencyProperty.RegisterAttached("X", typeof (double), typeof (CameraPanel), new UIPropertyMetadata(0.0));

        public static readonly DependencyProperty YProperty =
            DependencyProperty.RegisterAttached("Y", typeof (double), typeof (CameraPanel), new UIPropertyMetadata(0.0));

        public static readonly DependencyProperty ZProperty =
            DependencyProperty.RegisterAttached("Z", typeof (double), typeof (CameraPanel), new UIPropertyMetadata(0.0));


        public Camera Camera
        {
            get { return (Camera) GetValue(CameraProperty); }
            set { SetValue(CameraProperty, value); }
        }

        public static double GetZ(DependencyObject obj)
        {
            return (double) obj.GetValue(ZProperty);
        }

        public static void SetZ(DependencyObject obj, double value)
        {
            obj.SetValue(ZProperty, value);
        }

        // Using a DependencyProperty as the backing store for Z.  This enables animation, styling, binding, etc...


        public static double GetY(DependencyObject obj)
        {
            return (double) obj.GetValue(YProperty);
        }

        public static void SetY(DependencyObject obj, double value)
        {
            obj.SetValue(YProperty, value);
        }

        // Using a DependencyProperty as the backing store for Y.  This enables animation, styling, binding, etc...


        public static double GetX(DependencyObject obj)
        {
            return (double) obj.GetValue(XProperty);
        }

        public static void SetX(DependencyObject obj, double value)
        {
            obj.SetValue(XProperty, value);
        }

        // Using a DependencyProperty as the backing store for X.  This enables animation, styling, binding, etc...


        protected override Size ArrangeOverride(Size finalSize)
        {
            Camera3D2DProjector projector = Projector;
            if (projector == null)
                return finalSize;
            {
                //   new Camera3D2DProjector(Camera, finalSize);
            }
            foreach (FrameworkElement e in InternalChildren)
            {
                Point pt = projector.Point3DToPoint2D(new Point3D(GetX(e), GetY(e), GetZ(e)));
                Size s = e.DesiredSize;
                switch (e.HorizontalAlignment)
                {
                    case HorizontalAlignment.Left: pt.Offset(-s.Width, 0);
                        break;
                    case HorizontalAlignment.Center:
                    case HorizontalAlignment.Stretch: pt.Offset(-s.Width / 2, 0);
                        break;
                }
                switch (e.VerticalAlignment)
                {
                    case VerticalAlignment.Top: pt.Offset(0, -s.Height);
                        break;
                    case VerticalAlignment.Center:
                    case VerticalAlignment.Stretch: pt.Offset(0, -s.Height / 2);
                        break;
                }
                e.Arrange(new Rect(pt, e.DesiredSize));
            }
            return base.ArrangeOverride(finalSize);
        }


        protected override Size MeasureOverride(Size availableSize)
        {
            var result = new Size();
            foreach (UIElement e in InternalChildren)
            {
                e.Measure(availableSize);
                result =
                    new Size(Math.Max(result.Width, e.DesiredSize.Width), Math.Max(result.Height, e.DesiredSize.Height));
            }
            return result;
        }
    }
}